package czxy.tomcat.utils;

import com.czxy.tomcat.servlet.Servlet;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 该类仅可以在标记了TODO 的位置编写代码
 * 其他代码，同学不可改
 */
public class TomcatServer {
    private static TomcatServer tomcatServer;

    static {
        try {
            tomcatServer = new TomcatServer(TomcatUtils.PARAM_XML_FILENAME);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    public static Map<String, Object> serverMap;


    //TODO 仅可以在此定义成员变量 或 静态成员变量
    private TomcatServer(String param_xml_filename) throws DocumentException {
        List<Map> servList = new ArrayList<>();
        List<Map> servMapingList = new ArrayList<>();
        SAXReader saxReader = new SAXReader();
        Document read = saxReader.read(param_xml_filename);
        Element rootElement = read.getRootElement();
        List<Element> elements = rootElement.elements();
        for (Element e : elements) {
            if (e.getName().equals("servlet")) {
                List<Element> elements1 = e.elements();
                Map<String, String> servMap = new HashMap<>();
                for (Element e1 : elements1) {
                    if (e1.getName().equals("servlet-name") && !e1.getText().isEmpty()) {
                        servMap.put("servlet-name", e1.getText());
                    }
                    if (e1.getName().equals("servlet-class") && !e1.getText().isEmpty()) {
                        servMap.put("servlet-class", e1.getText());
                    }
                    if (e1.getName().equals("load-on-startup") && !e1.getText().isEmpty()) {
                        servMap.put("load-on-startup", e1.getText());
                    }

                }
                servList.add(servMap);
            }
            if (e.getName().equals("servlet-mapping")) {
                List<Element> elements1 = e.elements();
                Map<String, String> servMapingMap = new HashMap<>();
                for (Element e1 : elements1) {
                    if (e1.getName().equals("servlet-name") && !e1.getText().isEmpty()) {
                        servMapingMap.put("servlet-name",e1.getText());
                    }
                    if (e1.getName().equals("url-pattern") && !e1.getText().isEmpty()) {
                        servMapingMap.put("url-pattern", e1.getText());
                    }
                }
                servMapingList.add(servMapingMap);
            }

        }


        serverMap = new HashMap<>();
        for (Map<String, String> mp : servList) {
            for (Map<String, String> mp1 : servMapingList) {
                if (!mp.get("servlet-name").isEmpty() && mp.get("servlet-name").equals(mp1.get("servlet-name")) && !mp.get("servlet-class").isEmpty() && !mp1.get("url-pattern").isEmpty()) {
                    Servlet sv = null;
                    if (mp.get("load-on-startup")!=null&&!mp.get("load-on-startup").isEmpty()) {
                        try {
                            //通过反射的方式创建对象
                            sv = (Servlet) Class.forName(mp.get("servlet-class")).newInstance();
                            sv.init();
                            serverMap.put(mp1.get("url-pattern"), sv);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else {
                        serverMap.put(mp1.get("url-pattern"), mp.get("servlet-class"));
                    }
                }

            }
        }
        //TODO 题二：根据传入的xml文件名，加载xml文件
        // 要求：①加载对应关系：根据servlet-mapping的url-pattern值，就能找到相对应的 servlet的servlet-class值
        //       ②反射加载优先类及其init方法：
        //          凡是某servlet标签下有load-on-startup标签，都要反射创建该servlet下servlet-class全类名 的对象保存，并执行对应该对象的init方法
        //       ③若该构造方法运行时出错，无论任何错误，都不在控制台展示任何内容
    }

    public static TomcatServer getInstance() {

        return tomcatServer;
    }

    public Servlet getServlet(String url_pattern) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //TODO 题三：根据传入的url_pattern参数，在xml中寻找对应的Servlet返回
        // 要求：①若该url_pattern对应的Servlet第一次获取，则在“该方法中”反射创建该servlet，执行其init方法，最后返回servlet对象
        //       ②若该url_pattern对应的Servlet不是第一次获取、或在构造方法中执行过该Servlet的init方法，则直接返回servlet对象
        //
        Servlet sv = null;
        if (serverMap.get(url_pattern) instanceof Servlet) {
            sv = (Servlet) serverMap.get(url_pattern);
        } else {
            sv = (Servlet) Class.forName((String) serverMap.get(url_pattern)).newInstance();
            sv.init();
            serverMap.put(url_pattern, sv);
        }
        return sv;
    }

}
